# Home profile
# This class should be used to maintain the overall profile of the home
# All the device information is maintained here.
# An interface to future GUI realted information can be maintained here.

import util
import device
import constants
import os.path

from joinlogger import logger

class HomeProfile:
    def __init__(self):
        self.macs = {} # All the macs appearing on the network, this include devices macs as well as macs of the AP
        self.ap_macs = [] # Only AP_MACS
        self.assoc_macs = [] # Only other MACs associated with the AP
        # List of Device Objects inside the home
        self.devices = []
        self.dev_names = {} # A dict with keys of MACs and device Names 
        self.dev_locs = {} # A dict with keys of MACs and device Locations
        self.dev_status = {} # Key is date and time and value if list of [mac,joined/left]
        pass
    pass
    
    def get_macs(self): 
        return self.macs

    def get_ap_macs(self): 
        return self.ap_macs
   
    def get_assoc_macs(self): 
        return self.assoc_macs
    # --
    # MAC should be provided in this format
    # 00:1f:16:0b:54:52
    # --
    def add_mac(self,mac):
        if(mac.find(":") == -1):
            mac_add = util.add_colons_to_mac(mac)
        else:
            mac_add = mac
        if(len(mac_add) == 12+5):
            if not (self.macs.has_key(mac_add)):
                self.macs[mac_add] = True
                #print "All Devices:",self.macs
                pass
            pass
        else: 
            print "MAC address is provided in wrong format."
            print mac
        pass
    pass
    # --
    # MAC should be provided in this format
    # 00:1f:16:0b:54:52
    # --
    def addAssocDevice(self,mac):
        if(mac.find(":") == -1):
            mac_add = util.add_colons_to_mac(mac)
        else:
            mac_add = mac
        if(len(mac_add) == 12+5):
            if mac_add not in self.assoc_macs:
                self.assoc_macs.append(mac_add)
                print "Associated Devices:",self.assoc_macs
        else: 
            print "MAC address is provided in wrong format"
            print mac
            pass
        # Removing it as it works on AP only...
        self.verifyAssocClients() #Sanitizing and only including those which have got the lease

    # --
    # Removes the client from list of associated MACS. Client is outside the range.
    # Bilal: I have tested this manually on the wireless router.
    # as soon as we turn off the antenna its reflected in the output
    # of the command.
    # This function is needed apart from verifyAssocClients to get 
    # live addition/removal of devices.
    # --
    def remAssocDevice(self,mac):
        #print "Device left the network: "+ str(mac)
        if mac in self.assoc_macs:
            self.assoc_macs.remove(mac)

    def addAPMAC(self,mac):
        self.ap_macs.append(mac)
    
    def getAPMACs(self):
        return self.ap_macs

    # --
    # Checks if we have already created an object for the device
    #--
    def isDevPresent(self,mac):
        if(len(self.devices) == 0):
            return False
            pass
        pass
        for item in self.devices:
            if (item.getDeviceID() == mac):
                return True
                
    # --
    # Instantiate a Device using Device class and add it to the list of Devices
    # --
    def addDevice(self,mac):
        if not self.isDevPresent(mac):
            dev = device.Device(mac) 
            if(self.dev_names.has_key(mac)):
                dev.setDeviceName(self.dev_names[mac])
            if(self.dev_locs.has_key(mac)):
                dev.setDeviceLoc(self.dev_locs[mac])
                dev.setDeviceType("Fixed")
            else:
                dev.setDeviceType("Mobile")
                pass
            pass
            self.devices.append(dev)
            dev.printDevInfo()

    # --
    # This funciton reads the configuration file or any other 
    # method that we figure out for user to get the device location
    # information from user.
    # For now:its read from con/devices
    # --
    def readDevInfo(self):
        file_path = constants.DEVICE_CONF_FILE; 
        try:
            file_ref = open(file_path,"r")
        except IOError:
            print "conf File not found"

        conf_file = ""
        for line in file_ref:
            if(line[0] != '#'):
                conf_file += line
                t_list = line.split(",")
                if(len(t_list) ==3):
                    self.dev_names[t_list[0]] = t_list[1].strip()
                    self.dev_locs[t_list[0]] = t_list[2].strip()
                else:
                    print "There is problem in the configuration file for the devices"
                pass
            pass
        pass
        file_ref.close()
        #print self.dev_names
        #print self.dev_locs

    # --
    # Return list of machines that have been assigned an IP.
    # --
    def getDHCPClients(self):
        mac_list = []
        if(os.path.isfile(constants.DHCP_LEASE_FILE)):
            f = open(constants.DHCP_LEASE_FILE,'r')
            for line in f.readlines():
                if(len(line) > 1):
                    mac = line.split()[1]
                    mac_list.append(mac)
                else:
                    print "Error: Reading dhcp leases file."
            return mac_list
        else:
            print "Error: DHCP Lease file does not exist"
    # --
    # Verify the clients that have been assigned IP through DHCP.
    # This function reads dhcp file for clients
    # --
    def verifyAssocClients(self):
        mac_list = self.getDHCPClients()
        for k in self.assoc_macs:
            if k not in mac_list:
                #self.assoc_macs.remove(k)
                self.remAssocDevice(k)
                pass
            pass
        pass
        #print self.assoc_macs

    # --
    # Function to log the devices joining and leaving the network.
    # --
    def logDevice(self,mac,status):
        # Time: [mac,status]
        if(status == "joined"):
            log_str = mac + ",join"
            logger.info(log_str)
        pass
        if(status == "left"):
            log_str = mac + ",left"
            logger.info(log_str)
        pass

    
